package com.zx.mes.longactiviti.controller;

import com.zx.mes.hyl.common.pagemodel.Schedule;
import com.zx.mes.hyl.common.pagemodel.activiti.HistoricActivityInstanceEntity;
import com.zx.mes.hyl.common.pagemodel.activiti.HistoricTaskInstanceEntity;
import com.zx.mes.hyl.common.pagemodel.activiti.ProcessDefinitionEntity;
import com.zx.mes.hyl.common.pagemodel.activiti.TaskEntity;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngines;

import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import java.io.InputStream;
import java.util.*;
import java.util.zip.ZipInputStream;


/**
 * @author hyl
 * @date 2017-11-23
 */
@Controller
@RequestMapping("activitiController")
public class ActivitiController {

    /**
     * 获取默认的流程引擎实例  会自动读取activiti.cfg.xml文件
     */
    private ProcessEngine processEngine= ProcessEngines.getDefaultProcessEngine();

    private static Logger logger=Logger.getLogger(ActivitiController.class);

    /**
     * 部署流程定义
     * 由于有了自动的deploy所以这个方法一般不用
     */
    public void activitiDeployWithZip(){
        //获取当前class对象
        InputStream inputStream=this.getClass()
                                        //获取类加载器
                                        .getClassLoader()
                                        //获取指定文件资源流
                                        .getResourceAsStream("processes/helloWorld.zip");
        ZipInputStream zipInputStream=new ZipInputStream(inputStream);
        //部暑service
        Deployment deployment=processEngine.getRepositoryService()
                                    //创建部暑
                                    .createDeployment()
                                    //流程名称
                                    .name("helloworld流程")
                                    //添加zip输入流
                                    .addZipInputStream(zipInputStream)
                                    .deploy();
        logger.debug("流程部暑ID:"+deployment.getId());
        logger.debug("流程部暑Name"+deployment.getName());
    }


    /**
     * 查询流程定义 返回流程定义集合 ---对应act_re_procdef
     * @param processDefinitionKey myProcess_1
     * @return list
     */
    @RequestMapping("/listProcDef/{processDefinitionKey}")
    @ResponseBody
    public List<ProcessDefinitionEntity> list(@PathVariable String processDefinitionKey){
        List<ProcessDefinitionEntity> list=new ArrayList();
        List<ProcessDefinition> pdList=processEngine.getRepositoryService()
                .createProcessDefinitionQuery()
                .processDefinitionKey(processDefinitionKey)
                .list();
        for(int i=0;i<pdList.size();i++){
            logger.debug("ID:"+pdList.get(i).getId());
            logger.debug("NAME"+pdList.get(i).getName());
            logger.debug("KEY:"+pdList.get(i).getKey());
            logger.debug("VERSION"+pdList.get(i).getName());
            logger.debug("--------------------------------------");
            ProcessDefinitionEntity  pde=new ProcessDefinitionEntity();
            pde.setId(pdList.get(i).getId());
            pde.setName(pdList.get(i).getName());
            pde.setKey(pdList.get(i).getKey());
            pde.setVersion(pdList.get(i).getVersion());
            list.add(pde);
        }
        return list;
    }

    /**
     * 通过ID查询当个流程定义
     * @param processDefinitionId  myProcess_1:4:30007
     * @return pde
     */
    @RequestMapping("/listById/{processDefinitionId}")
    @ResponseBody
    public ProcessDefinitionEntity getById(@PathVariable String processDefinitionId){
        ProcessDefinitionEntity  pde=new ProcessDefinitionEntity();

        ProcessDefinition pd=processEngine.getRepositoryService()
                .createProcessDefinitionQuery()
                .processDefinitionId(processDefinitionId)
                .singleResult();

        logger.debug("ID:"+pd.getId());
        logger.debug("NAME"+pd.getName());
        logger.debug("KEY:"+pd.getKey());
        logger.debug("VERSION"+pd.getName());

        pde.setId(pd.getId());
        pde.setName(pd.getName());
        pde.setKey(pd.getKey());
        pde.setVersion(pd.getVersion());
        return pde;
    }

    /**
     *查询所有最新版本的流程定义
     * @return listReturn
     */
    @RequestMapping("/listLastVersion")
    @ResponseBody
    public List<ProcessDefinitionEntity> listLastVersion(){
        List<ProcessDefinitionEntity> listReturn=new ArrayList();

        List<ProcessDefinition> list=processEngine.getRepositoryService()
                .createProcessDefinitionQuery()
                .orderByProcessDefinitionVersion()
                .asc()
                .list();

        // 定义有序map
        Map<String,ProcessDefinition> map=new LinkedHashMap<String, ProcessDefinition>();
        for (int i=0;i<list.size();i++){
            map.put(list.get(i).getKey(),list.get(i));
        }
        List<ProcessDefinition> pdList=new LinkedList<>(map.values());

        for (int j=0;j<pdList.size();j++){
            logger.debug("ID:"+pdList.get(j).getId());
            logger.debug("NAME"+pdList.get(j).getName());
            logger.debug("KEY:"+pdList.get(j).getKey());
            logger.debug("VERSION"+pdList.get(j).getName());
            logger.debug("--------------------------------------");
            ProcessDefinitionEntity  pde=new ProcessDefinitionEntity();
            pde.setId(pdList.get(j).getId());
            pde.setName(pdList.get(j).getName());
            pde.setKey(pdList.get(j).getKey());
            pde.setVersion(pdList.get(j).getVersion());
            listReturn.add(pde);
        }
        return listReturn;
    }

    /**
     * 历史任务(由分配的办理人来查询)
     * @param assignee aaa
     * @return listReturn
     */
    @RequestMapping(value = "/historyTaskList/{assignee}",method = RequestMethod.GET)
    public List<HistoricTaskInstanceEntity> historyTaskList(@PathVariable String assignee){
        List<HistoricTaskInstanceEntity> listReturn =new ArrayList();
        // 历史任务Service
        List<HistoricTaskInstance> list=processEngine.getHistoryService()
                // 创建历史任务实例查询
                .createHistoricTaskInstanceQuery()
                // 指定办理人
                .taskAssignee(assignee)
                // 查询已经完成的任务
                .finished()
                .list();
        for(HistoricTaskInstance hti:list){
            System.out.println("任务ID:"+hti.getId());
            System.out.println("流程实例ID:"+hti.getProcessInstanceId());
            System.out.println("班里人："+hti.getAssignee());
            System.out.println("创建时间："+hti.getCreateTime());
            System.out.println("结束时间："+hti.getEndTime());
            System.out.println("===========================");
            HistoricTaskInstanceEntity hte=new HistoricTaskInstanceEntity();
            hte.setId(hti.getId());
            hte.setProcessInstanceId(hti.getProcessInstanceId());
            hte.setAssignee(hti.getAssignee());
            hte.setCreateTime(hti.getCreateTime());
            hte.setEndTime(hti.getEndTime());
        }
        return listReturn;
    }

    /**
     * 历史活动查询(某一个流程一次执行过程)
     * @param processInstanceId
     * @return listReturn
     */
    @RequestMapping(value = "/historyActInstanceList/{processInstanceId}")
    public List<HistoricActivityInstanceEntity> historyActInstanceList(@PathVariable String processInstanceId){

        List<HistoricActivityInstanceEntity> listReturn=new ArrayList();

        // 历史任务Service
        List<HistoricActivityInstance> list=processEngine.getHistoryService()
                // 创建历史活动实例查询
                .createHistoricActivityInstanceQuery()
                // 指定流程实例id
                .processInstanceId(processInstanceId)
                // 查询已经完成的任务
                .finished()
                .list();
        for(HistoricActivityInstance hai:list){
            System.out.println("任务ID:"+hai.getId());
            System.out.println("流程实例ID:"+hai.getProcessInstanceId());
            System.out.println("活动名称："+hai.getActivityName());
            System.out.println("办理人："+hai.getAssignee());
            System.out.println("开始时间："+hai.getStartTime());
            System.out.println("结束时间："+hai.getEndTime());
            System.out.println("===========================");

            HistoricActivityInstanceEntity haie=new HistoricActivityInstanceEntity();
            haie.setId(hai.getId());
            haie.setProcessInstanceId(hai.getProcessInstanceId());
            haie.setActivityName(hai.getActivityName());
            haie.setAssignee(hai.getAssignee());
            haie.setStartTime(hai.getStartTime());
            haie.setEndTime(hai.getEndTime());
        }

        return listReturn;
    }

    /**
     * 启动流程实例
     */
    @RequestMapping(value = "/start/{processDefinitionKey}",method = RequestMethod.GET)
    public void start(@PathVariable String processDefinitionKey){
        //启动并获取流程实例

        //运行时流程实例Service
        ProcessInstance processInstance=processEngine.getRuntimeService()
                //流程定义表的KEY字段值
                .startProcessInstanceByKey(processDefinitionKey);
        logger.debug("流程定义ID"+processInstance.getId());
        logger.debug("流程定义ID"+processInstance.getProcessDefinitionId());
    }


    /**
     * 按指定办理人查看任务
     * @param assignee (指定办理人)
     * @return listReturn
     */
    @RequestMapping(value = "/findTaskbyAssignee/{assignee}")
    @ResponseBody
    public List<TaskEntity> findTaskbyAssignee(@PathVariable String assignee){
        List<TaskEntity> listReturn =new ArrayList();

        List<Task> taskList=processEngine.getTaskService()
                .createTaskQuery()
                .taskAssignee(assignee)
                .list();
        for (int i=0;i<taskList.size();i++){
            TaskEntity taskEntity=new TaskEntity();
            taskEntity.setId(taskList.get(i).getId());
            taskEntity.setName(taskList.get(i).getName());
            taskEntity.setCreateTime(taskList.get(i).getCreateTime());
            taskEntity.setAssignee(taskList.get(i).getAssignee());
            taskEntity.setProcessInstanceId(taskList.get(i).getProcessInstanceId());
            listReturn.add(taskEntity);
        }
        return listReturn;
    }


    /**
     * 完成任务
     * @param taskId
     */
    @RequestMapping(value = "/completeTask",method = RequestMethod.GET)
    public void completeTask(String taskId){
        //任务相关Service
        processEngine.getTaskService()
                //完成指定的任务ID
                .complete(taskId);
    }

    /**
     * 设置流程变量及值
     * 假如节点不是任务节点的时候，只能用RuntimeService。接口和方法和TaskService一样的
     * @param taskId
     */
    @RequestMapping(value = "/set/{taskId}",method = RequestMethod.GET)
    public void setVariablesValues(@PathVariable String taskId){

        //任务Service
        TaskService taskService=processEngine.getTaskService();
        //setVariableLocal仅在某个任务节点有作用
        taskService.setVariableLocal(taskId,"x1",2);
        //在整个流程实例都有效
        taskService.setVariable(taskId,"x2",new Date());
        Schedule schedule=new Schedule();
        schedule.setId(33);
        schedule.setName("排程一");
        taskService.setVariable(taskId,"schedule",schedule);
    }

    @RequestMapping(value = "/get/{taskId}",method = RequestMethod.GET)
    public void getVariablesValue(@PathVariable String taskId){
        //任务Service
        TaskService taskService=processEngine.getTaskService();
        Integer x1= (Integer) taskService.getVariable(taskId,"x1");
        Date date= (Date) taskService.getVariable(taskId,"x2");
        Schedule schedule= (Schedule) taskService.getVariable(taskId,"schedule");

        logger.debug("x1:"+x1);
        logger.debug("x2:"+date);
        logger.debug("schedule:"+schedule.getId()+" "+schedule.getName());

    }



}
